package com.thesis.manage.common.handler;


import com.thesis.manage.common.constant.EmailContent;
import com.thesis.manage.common.email.EmailSendUtil;
import com.thesis.manage.common.entity.ExceptionLog;
import com.thesis.manage.common.exception.CommonException;
import com.thesis.manage.common.service.ExceptionLogService;
import com.thesis.manage.common.utils.IpUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.regex.Pattern;

/**
 * @author php
 * @date 2018/3/20
 * 异常处理
 */
@Aspect
public class RpcExceptionHandler {
    private static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
    private static final Logger LOGGER = LoggerFactory.getLogger(RpcExceptionHandler.class);
    private static final String SUBJECT = "异常日志";
    @Value("${spring.application.name}")
    private String applicationName;
    /**
     * 接受异常邮箱
     */
    @Value("${error.accept.email}")
    private String errorAcceptEmail;
    @Resource
    private EmailSendUtil emailSendUtil;
    @Resource
    private ExceptionLogService exceptionLogService;

    /**
     * 代表使用这个注解的类和子类的所有方法都能被包含
     */
    @Pointcut("@within(com.thesis.manage.common.constant.OpenException)")
    public void aspect() {
    }

    @AfterThrowing(pointcut = "aspect()", throwing = "e")
    public void throwException(Throwable e) {
        //判断是否是自定义错误
        if (!(e instanceof CommonException)) {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            HttpServletResponse response = requestAttributes.getResponse();
            //异常信息封装
            String url = request.getRequestURL().toString();
            ExceptionLog exceptionLog = new ExceptionLog();
            exceptionLog.setIp(IpUtil.getIpAddr(request));
            exceptionLog.setServerName(applicationName);
            exceptionLog.setUrl(url);
            exceptionLog.setMethod(request.getMethod());
            exceptionLog.setMessage(e.getMessage());
            exceptionLog.setCode(response.getStatus());
            exceptionLogService.insert(exceptionLog);
            //记录日志
            LOGGER.error("{},接口发生了如下错误,{}", url, e);
            //发送邮件通知
            if (StringUtils.isNotBlank(errorAcceptEmail)) {
                String[] emails = errorAcceptEmail.split(",");
                for (String email : emails) {
                    if (Pattern.matches(REGEX_EMAIL, email)) {
                        //邮件模板
                        StringBuilder context = EmailContent.context(email, applicationName, exceptionLog);
                        this.emailSendUtil.sendHtml(email, this.applicationName + SUBJECT, context.toString());
                    } else {
                        throw new CommonException("email error", "邮箱格式错误");
                    }
                }
            }

        }
    }
}
